#include <kutils.h>
#include <string.h>
#include "ata.h"
#include "display.h"
#include "memory.h"
#include "syscall.h"
#include "vfs.h"

s32int ata_open_fs(fs_node_t *node);
s32int ata_close_fs(fs_node_t *node);
s32int ata_read_fs(fs_node_t *node, u32int offset, u32int size, u8int *buffer);
s32int ata_create_dev_file(s8int *name);

extern ata_drive_t *drives[4];//4 drives each with 4 partitions
extern s8int d_exists[4];
extern fs_node_t *fs_root;

s32int ata_open_fs(fs_node_t *node)
{
	if(!node)
		return 0;
	//a dummy open function
	return 1;
}

s32int ata_close_fs(fs_node_t *node)
{
	if(!node)
		return 0;
	//a dummy close function
	return 1;
}

s32int ata_read_fs(fs_node_t *node, u32int offset, u32int size, u8int *buffer)
{
	if(strcmp((const s8int*)node->name,"disk0part0") == 0)
	{
		return ata_read_partition(&drives[0]->partitions[0], buffer, offset, 0, size);
	}
	if(strcmp((const s8int*)node->name,"disk0part1") == 0)
	{
		return ata_read_partition(&drives[0]->partitions[1], buffer, offset, 0, size);
	}
	if(strcmp((const s8int*)node->name,"disk0part2") == 0)
	{
		return ata_read_partition(&drives[0]->partitions[2], buffer, offset, 0, size);
	}
	if(strcmp((const s8int*)node->name,"disk0part3") == 0)
	{
		return ata_read_partition(&drives[0]->partitions[3], buffer, offset, 0, size);
	}
	return 0;
}

//creates a file in the /dev directory through which a device can be read/written
s32int ata_create_dev_file(s8int *name)
{
	fs_node_t *dev_node = fs_root->first_child;

	if(!dev_node)
		return 0;	

	fs_node_t *new_node = (fs_node_t*)kmalloc(sizeof(fs_node_t));
	strcpy((s8int*)new_node->name,name);
	new_node->length = 512; //the standard block size
	new_node->inode = get_valid_inode();
	new_node->flags = FS_FILE;
	new_node->read = &ata_read_fs;
   new_node->write = 0;
   new_node->open = &ata_open_fs;
   new_node->close = &ata_close_fs;
   new_node->ptr = 0;
	new_node->dvr_num = 0;
	new_node->dvr_ptr = 0;
	new_node->parent = dev_node;//it's parent is the /dev node
	new_node->next_sibling = 0;
	new_node->first_child = 0;

	if(dev_node->first_child == 0)//the dev node has no children at this time
	{
		dev_node->first_child = new_node;
	}
	else//the dev node alredy has atleast one child, let's add this new one to the end of the linked list
	{
		fs_node_t *tmp_node = dev_node->first_child;
		while(tmp_node)
		{
			if(tmp_node->next_sibling)
			{
				tmp_node = tmp_node->next_sibling;
			}
			else
			{
				tmp_node->next_sibling = new_node;
				break;
			}
		}
	}

	return 1;
}

void init_ata_interface(void)
{
	// this function will add all of the detected partitions to 
	// the /dev directory and expose their read/write functions
	// to the proper wrapper functions in this file
	int i,j = 0;
	for(i = 0; i < 4; i++)
	{
		if(d_exists[i])
		{
			for(j = 0; j < 4; j++)
			{
				if(drives[i]->partitions[j].exists)
				{
					s8int* device_name = (s8int*)kmalloc(12);
					strcpy(device_name, "disk part ");
					device_name[4] = (s8int)('0' + i);
					device_name[9] = (s8int)('0' + j);
					device_name[10] = 0;
					ata_create_dev_file(device_name);
					kfree(device_name);
				}
			}
		}
	}
}
